#include "xSceneNode.h"
#include "xRenderObject.h"
#include "xLine3D.h"


namespace XE
{

	xSceneNode::xSceneNode(xSceneManager * pCreate,xSceneNode* pParent,const xString& name)
		:xNode(pParent,name),m_pSceneManager(pCreate),m_pLine(NULL),m_Visible(true)
	{

	}

	 xSceneNode::~xSceneNode()
	 {
		DetachAllRenderObject();
		if(m_pLine!=NULL)
			m_pSceneManager->DestoryRenderObject(m_pLine);
		// xNode::~xNode();
	
	 }

	 void xSceneNode::DetachAllRenderObject()
	 {
		 RenderObjectMap::iterator it = m_RenderObjectMap.begin();
         RenderObjectMap::iterator itend = m_RenderObjectMap.end();
		 for(;it!=itend;++it)
		 {
			if(it->second!=NULL)
				it->second->m_pAttachNode=NULL;
		 }
		 m_RenderObjectMap.clear();
		m_Box.Reset();
		 return ;
	 }

	 bool  xSceneNode::DetachRenderObject(xRenderObject* pObje)
	 {
		 if(pObje==NULL)
			 return false;
		  RenderObjectMap::iterator it = m_RenderObjectMap.find(pObje->GetName());
		  if(it!=m_RenderObjectMap.end())
		  {
			 pObje->NotifyDeath(this);
			  m_RenderObjectMap.erase(it);

			  return true;
		  }

		  return false;
	 }


	 size_t xSceneNode::GetAttachRenderObjectNumber() const
	 {
		 return m_RenderObjectMap.size();

	 }

	 bool xSceneNode::AttachRenderObject(xRenderObject* pObect)
	 {
        if(pObect==NULL||pObect->GetAttachSceneNode()!=NULL)
			return false;
		xRenderObject* ptemObje = GetAttachRenderObject(pObect->GetName());
		if(ptemObje!=NULL)
			return false;
		m_RenderObjectMap.insert(std::make_pair(pObect->GetName(),pObect));
		pObect->NotifyAttach(this);
		//pObect->m_pAttachNode = this;

		
		return true;
	 }

	 xRenderObject* xSceneNode::GetAttachRenderObject(const xString& name)
	 {
		 RenderObjectMap::iterator it  = 	 m_RenderObjectMap.find(name);
		 if(it!=m_RenderObjectMap.end())
		 {
			 return it->second;
		 }
		 return NULL;
	 }


	 RenderObjectMapIterator xSceneNode::GetRenderObjectIterator()
	 {
		 RenderObjectMapIterator it(m_RenderObjectMap.begin(),m_RenderObjectMap.end());
		 return it;
	 }



	 xRenderObject*  xSceneNode::GetAttachRenderObject(UINT index)
	 {
		 if(index>m_RenderObjectMap.size()-1)
			 return NULL;
		  RenderObjectMap::iterator it  = 	 m_RenderObjectMap.begin();
		  for(UINT i = 0;i<index;++i)
			  ++it;
		  return it->second;

	 }

	 void  xSceneNode::updateRenderQueue(const xCamera* pCamera)
	 {

		
		 RenderObjectMap::iterator it = m_RenderObjectMap.begin();
		 RenderObjectMap::iterator itend = m_RenderObjectMap.end();
		 for(;it!=itend;++it)
		 {
			 xRenderObject* pRenderObj = it->second;

			 if(pRenderObj==NULL)
				 continue;
			// m_pSceneManager->GetRenderQueue(it->second->GetRenderQueueLevel())->AddRenderObject(it->second);
			 pRenderObj->_updateRenderQueue(m_pSceneManager->GetRenderQueue(pRenderObj->GetRenderQueueLevel()),pCamera);
			
		 }

		 if(IsRender()&&m_pLine!=NULL)
		 {
			 m_pSceneManager->GetRenderQueue( m_pLine->GetRenderQueueLevel())->AddRenderObject(m_pLine);

		 }

		 return;

	 }


	 void xSceneNode::_updateBuildBox()
	 {
		
	      m_Box.Reset();

		  RenderObjectMap::iterator it = m_RenderObjectMap.begin();
		  RenderObjectMap::iterator itend = m_RenderObjectMap.end();
		 for(;it!=itend;++it)
		 {
			const xBox* pLocalBox =  it->second->GetWorldBox();
			if(pLocalBox==NULL)
				continue;
            m_Box.MergeBox(*pLocalBox);
		 }

		// m_Box.TransForm(*GetWorldMatrix());
		 if(m_pLine!=NULL)
		 {
			 m_pLine->Lock();
		      m_pLine->SetPoint(0,m_Box.GetCorner(0));
			  m_pLine->SetPoint(1,m_Box.GetCorner(1));

			  m_pLine->SetPoint(2,m_Box.GetCorner(1));
			  m_pLine->SetPoint(3,m_Box.GetCorner(2));

			  m_pLine->SetPoint(4,m_Box.GetCorner(2));
			  m_pLine->SetPoint(5,m_Box.GetCorner(3));

			  m_pLine->SetPoint(6,m_Box.GetCorner(3));
			  m_pLine->SetPoint(7,m_Box.GetCorner(0));
//------------------------------------------------------------
			  m_pLine->SetPoint(8,m_Box.GetCorner(4));
			  m_pLine->SetPoint(9,m_Box.GetCorner(5));

			  m_pLine->SetPoint(10,m_Box.GetCorner(5));
			  m_pLine->SetPoint(11,m_Box.GetCorner(6));

			  m_pLine->SetPoint(12,m_Box.GetCorner(6));
			  m_pLine->SetPoint(13,m_Box.GetCorner(7));

			  m_pLine->SetPoint(14,m_Box.GetCorner(7));
			  m_pLine->SetPoint(15,m_Box.GetCorner(4));
//--------------------------------------------------------

			  m_pLine->SetPoint(16,m_Box.GetCorner(1));
			  m_pLine->SetPoint(17,m_Box.GetCorner(5));

			  m_pLine->SetPoint(18,m_Box.GetCorner(2));
			  m_pLine->SetPoint(19,m_Box.GetCorner(4));

			  m_pLine->SetPoint(20,m_Box.GetCorner(3));
			  m_pLine->SetPoint(21,m_Box.GetCorner(7));

			  m_pLine->SetPoint(22,m_Box.GetCorner(0));
			  m_pLine->SetPoint(23,m_Box.GetCorner(6));



			 m_pLine->unLock();
		 }		
			 	
		 return ;

	 }


	 void  xSceneNode::update(bool ParentChange,int& upNumber)
	 {
		 xNode::update(ParentChange,upNumber);
		 _updateBuildBox();
	 }


	 void  xSceneNode::EnableRender(bool b)
	 { 
		 m_isRender= b;
		 if(m_isRender)
		 {
			 XE::xLine3DCreateParameter lin3dPara(GetName()+"Node_line",24,XE::xColor(0.0f,0.0f,1.0f,1.0f));
			 m_pLine  =static_cast<XE::xLine3d*>(m_pSceneManager->CreateRenderObject(lin3dPara));
			 //AttachRenderObject(m_pLine);

		 }else
		 {
			 m_pSceneManager->DestoryRenderObject(m_pLine);
			 m_pLine=NULL;
		 }

	 }

	

	


}